#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
音乐播放器 MCP 服务

这是一个基于 MCP 协议的本地音乐播放器服务，允许通过小智AI控制本地音乐文件的播放。
支持播放、暂停、快进、快退、音量调节、循环模式设置等功能。
音乐文件默认存放在 d:/MCP/0/music/ 目录下。

依赖:
    - pygame: 用于音频播放
    - mcp.server.fastmcp: 用于创建MCP服务
"""

# 导入必要的库
from mcp.server.fastmcp import FastMCP  # MCP服务框架
import sys
import logging
import os
import pygame  # 用于音频播放
from pygame import mixer
import time
import random
import re
from collections import defaultdict

# 配置日志
logger = logging.getLogger('MusicPlayer')
logger.setLevel(logging.INFO)

# 修复Windows控制台的UTF-8编码问题
if sys.platform == 'win32':
    sys.stderr.reconfigure(encoding='utf-8')
    sys.stdout.reconfigure(encoding='utf-8')

# 初始化pygame音频系统
pygame.init()
mixer.init()

# 音乐文件夹路径配置
MUSIC_FOLDER = 'd:/music/'

# 全局状态变量
current_music = None  # 当前播放的音乐文件名
music_list = []  # 音乐文件列表
current_index = -1  # 当前音乐在列表中的索引
is_playing = False  # 播放状态标志
loop_mode = 0  # 循环模式: 0=不循环, 1=单曲循环, 2=列表循环
play_mode = 'random'  # 播放模式: 'random'=随机播放, 'sequential'=顺序播放

# 音乐文件完整路径映射和关键词索引
music_full_paths = {}  # {文件名: 完整路径}
music_index = defaultdict(list)  # {关键词: [文件名列表]}

# 检查音乐文件夹是否存在
if not os.path.exists(MUSIC_FOLDER):
    logger.warning(f"音乐文件夹不存在: {MUSIC_FOLDER}")
    # 尝试创建音乐文件夹
    try:
        os.makedirs(MUSIC_FOLDER)
        logger.info(f"已创建音乐文件夹: {MUSIC_FOLDER}")
    except Exception as e:
        logger.error(f"创建音乐文件夹失败: {e}")

# 创建MCP服务器实例
mcp = FastMCP("MusicPlayer")

def load_music_list():
    """
    加载音乐文件夹中的所有MP3文件到音乐列表，并建立关键词索引
    
    Returns:
        list: 音乐文件名列表
    """
    global music_list, music_full_paths, music_index
    try:
        # 确保音乐文件夹存在
        if not os.path.exists(MUSIC_FOLDER):
            logger.error(f"音乐文件夹不存在: {MUSIC_FOLDER}")
            return []
            
        music_list = []
        music_full_paths = {}
        music_index = defaultdict(list)
        
        logger.info(f"开始扫描音乐文件夹: {MUSIC_FOLDER}")
        
        # 遍历音乐文件夹，筛选MP3文件（支持更多音频格式）
        audio_extensions = ['.mp3', '.wav', '.ogg', '.flac', '.m4a']
        for file in os.listdir(MUSIC_FOLDER):
            # 转换为小写进行扩展名匹配
            file_lower = file.lower()
            if any(file_lower.endswith(ext) for ext in audio_extensions):
                music_list.append(file)
                file_path = os.path.join(MUSIC_FOLDER, file)
                music_full_paths[file] = file_path
                
                # 建立关键词索引
                # 1. 提取文件名（不含扩展名）
                file_name_without_ext = os.path.splitext(file)[0].lower()
                
                # 2. 分割可能的歌手和歌曲名
                if '-' in file_name_without_ext:
                    parts = file_name_without_ext.split('-')
                    if len(parts) >= 2:
                        # 通常格式：歌手-歌曲名
                        singer = parts[0].strip()
                        song = '-'.join(parts[1:]).strip()
                        
                        # 添加歌手索引
                        if singer:
                            music_index[singer].append(file)
                        # 添加歌曲名索引
                        if song:
                            music_index[song].append(file)
                
                # 3. 分词处理（简单的中文分词）
                # 提取所有可能的关键词
                keywords = re.findall(r'[\u4e00-\u9fa5a-zA-Z0-9]+', file_name_without_ext)
                for keyword in keywords:
                    if len(keyword) > 1:  # 关键词长度至少为2
                        music_index[keyword].append(file)
        
        # 去重索引中的文件名
        for keyword in music_index:
            music_index[keyword] = list(set(music_index[keyword]))
        
        # 按文件名排序，使播放顺序更稳定
        music_list.sort()
        
        logger.info(f"扫描完成，已加载 {len(music_list)} 个音频文件")
        logger.info(f"已建立 {len(music_index)} 个关键词索引")
        
        if music_list:
            logger.info(f"音乐列表中的前5首: {music_list[:5]}")
        else:
            logger.warning("音乐文件夹中没有找到音频文件")
            logger.warning(f"请将音乐文件放在: {MUSIC_FOLDER}")
        
        return music_list
    except Exception as e:
        logger.error(f"加载音乐列表失败: {e}")
        # 提供详细的错误信息，帮助诊断
        logger.error(f"请确认您有权限访问: {MUSIC_FOLDER}")
        return []

def search_music_by_keyword(keyword):
    """
    使用关键词索引搜索音乐
    
    Args:
        keyword (str): 搜索关键词
    
    Returns:
        list: 匹配的音乐文件列表
    """
    if not music_list:
        load_music_list()
    
    keyword = keyword.lower()
    results = set()
    
    # 1. 优先使用建立的索引
    if keyword in music_index:
        results.update(music_index[keyword])
        logger.info(f"通过索引找到 {len(results)} 个匹配结果")
    
    # 2. 如果索引没有找到，进行文件名模糊匹配
    if not results:
        for music in music_list:
            if keyword in music.lower():
                results.add(music)
    
    return list(results)

def search_music_by_singer(singer):
    """
    搜索特定歌手的歌曲
    
    Args:
        singer (str): 歌手名称
    
    Returns:
        list: 匹配的音乐文件列表
    """
    if not music_list:
        load_music_list()
    
    singer = singer.lower()
    results = []
    
    # 1. 优先使用索引
    if singer in music_index:
        # 验证是否真正匹配歌手（文件名中包含歌手名在'-'前）
        for music in music_index[singer]:
            file_name_lower = os.path.splitext(music)[0].lower()
            if '-' in file_name_lower:
                parts = file_name_lower.split('-', 1)
                if parts[0].strip() == singer:
                    results.append(music)
    
    # 2. 如果索引结果不理想，进行全面搜索
    if not results:
        for music in music_list:
            file_name_lower = os.path.splitext(music)[0].lower()
            if '-' in file_name_lower:
                parts = file_name_lower.split('-', 1)
                if singer in parts[0].strip():
                    results.append(music)
    
    return results

def get_random_music(exclude_current=True):
    """
    获取随机一首音乐
    
    Args:
        exclude_current (bool): 是否排除当前正在播放的音乐
    
    Returns:
        str: 随机音乐文件名，如果没有可用音乐则返回None
    """
    if not music_list:
        load_music_list()
        if not music_list:
            return None
    
    # 如果排除当前音乐且音乐列表长度大于1
    if exclude_current and current_music and len(music_list) > 1:
        available_music = [music for music in music_list if music != current_music]
        return random.choice(available_music)
    else:
        return random.choice(music_list)

def play_music(file_name=None):
    """
    播放音乐
    
    Args:
        file_name (str, optional): 要播放的音乐文件名，如果为None则根据播放模式选择
    
    Returns:
        dict: {
            "success": bool,  # 操作是否成功
            "message": str,   # 操作结果消息
            "file_path": str  # 文件完整路径
        }
    """
    global current_music, is_playing, current_index
    try:
        # 确保音乐列表已加载
        if not music_list:
            load_music_list()
            
        # 增强的模糊匹配算法
        if file_name:
            logger.info(f"接收到点歌请求: {file_name}")
            
            # 转换为小写进行比较
            file_name_lower = file_name.lower()
            matched_files = []
            
            # 1. 优先检查是否是歌手名搜索（包含'的歌'或'的歌曲'）
            if '的歌' in file_name_lower or '的歌曲' in file_name_lower:
                singer = file_name_lower.replace('的歌', '').replace('的歌曲', '').strip()
                if singer:
                    matched_files = search_music_by_singer(singer)
                    logger.info(f"搜索歌手 '{singer}' 的歌曲，找到 {len(matched_files)} 首")
                    
                    if matched_files:
                        # 随机选择一首该歌手的歌曲
                        file_name = random.choice(matched_files)
                        logger.info(f"随机选择播放: {file_name}")
                    else:
                        logger.warning(f"未找到歌手 '{singer}' 的歌曲")
            
            # 2. 如果不是歌手搜索，使用关键词搜索
            if not matched_files:
                matched_files = search_music_by_keyword(file_name_lower)
                
                # 处理匹配结果
                if len(matched_files) == 1:
                    # 唯一匹配，直接播放
                    file_name = matched_files[0]
                    logger.info(f"确定播放: {file_name}")
                elif len(matched_files) > 1:
                    # 多个匹配，随机选择一首
                    file_name = random.choice(matched_files)
                    logger.info(f"找到多首匹配的音乐，随机选择播放: {file_name}")
                else:
                    # 没有找到匹配，但仍然尝试播放（可能是直接文件名）
                    logger.warning(f"没有找到匹配 '{file_name}' 的音乐")
                    # 检查是否是完整文件名，如果是，直接尝试播放
                    if file_name.endswith(('.mp3', '.wav', '.ogg', '.flac', '.m4a')):
                        pass  # 直接使用提供的文件名
                    else:
                        # 尝试添加常见扩展名
                        for ext in ['.mp3', '.wav', '.ogg', '.flac', '.m4a']:
                            test_file = file_name + ext
                            if test_file in music_list:
                                file_name = test_file
                                logger.info(f"找到带扩展名的匹配: {file_name}")
                                break
        
        if file_name:
            # 播放指定文件
            # 优先使用完整路径映射
            if file_name in music_full_paths:
                file_path = music_full_paths[file_name]
            else:
                file_path = os.path.join(MUSIC_FOLDER, file_name)
            
            logger.info(f"尝试播放文件: {file_path}")
            
            if os.path.exists(file_path):
                mixer.music.load(file_path)
                current_music = file_name
                current_index = music_list.index(file_name) if file_name in music_list else -1
                logger.info(f"成功加载文件: {file_name}")
            else:
                logger.error(f"文件不存在: {file_path}")
                # 提供更详细的错误信息和可能的解决方案
                return {"success": False, "message": f"文件不存在: {file_name}，请检查文件名是否正确"}
        elif current_music:
            # 继续播放当前音乐
            logger.info(f"继续播放当前音乐: {current_music}")
        elif music_list:
            # 根据播放模式选择音乐
            if play_mode == 'random':
                # 随机播放
                current_music = get_random_music()
                if current_music in music_full_paths:
                    file_path = music_full_paths[current_music]
                else:
                    file_path = os.path.join(MUSIC_FOLDER, current_music)
                current_index = music_list.index(current_music) if current_music in music_list else -1
                logger.info(f"随机播放音乐: {current_music}")
                mixer.music.load(file_path)
            else:
                # 顺序播放
                current_index = 0
                current_music = music_list[current_index]
                file_path = os.path.join(MUSIC_FOLDER, current_music)
                logger.info(f"播放第一首音乐: {current_music}")
                mixer.music.load(file_path)
        else:
            logger.error("音乐列表为空，无法播放音乐")
            return {"success": False, "message": "音乐列表为空"}
        
        # 根据循环模式设置播放
        if loop_mode == 1:
            mixer.music.play(-1)  # 单曲循环
            logger.info(f"开始单曲循环播放: {current_music}")
        else:
            mixer.music.play()  # 普通播放
            logger.info(f"开始播放: {current_music}")
            
        is_playing = True
        # 返回完整路径，支持配合文件名修改工具使用
        full_path = music_full_paths.get(current_music, os.path.join(MUSIC_FOLDER, current_music))
        return {"success": True, "message": f"正在播放: {current_music}", "file_path": full_path}
    except Exception as e:
        logger.error(f"播放音乐失败: {e}", exc_info=True)
        return {"success": False, "message": f"播放失败: {str(e)}，可能需要安装pygame: pip install pygame"}

def pause_music():
    """
    暂停当前播放的音乐
    
    Returns:
        dict: {
            "success": bool,  # 操作是否成功
            "message": str    # 操作结果消息
        }
    """
    global is_playing
    try:
        mixer.music.pause()
        is_playing = False
        logger.info("音乐已暂停")
        return {"success": True, "message": "音乐已暂停"}
    except Exception as e:
        logger.error(f"暂停音乐失败: {e}")
        return {"success": False, "message": f"暂停失败: {str(e)}"}

def unpause_music():
    """
    恢复暂停的音乐播放
    
    Returns:
        dict: {
            "success": bool,  # 操作是否成功
            "message": str    # 操作结果消息
        }
    """
    global is_playing
    try:
        mixer.music.unpause()
        is_playing = True
        logger.info("音乐已恢复播放")
        return {"success": True, "message": "音乐已恢复播放"}
    except Exception as e:
        logger.error(f"恢复播放失败: {e}")
        return {"success": False, "message": f"恢复播放失败: {str(e)}"}

def stop_music():
    """
    停止当前播放的音乐
    
    Returns:
        dict: {
            "success": bool,  # 操作是否成功
            "message": str    # 操作结果消息
        }
    """
    global is_playing
    try:
        mixer.music.stop()
        is_playing = False
        logger.info("音乐已停止")
        return {"success": True, "message": "音乐已停止"}
    except Exception as e:
        logger.error(f"停止音乐失败: {e}")
        return {"success": False, "message": f"停止失败: {str(e)}"}

def next_music():
    """
    播放下一首音乐
    根据播放模式决定是随机播放还是顺序播放
    
    Returns:
        dict: {
            "success": bool,  # 操作是否成功
            "message": str    # 操作结果消息
        }
    """
    global current_index, current_music
    if not music_list:
        load_music_list()
    
    if music_list:
        if play_mode == 'random':
            # 随机播放模式
            next_music_file = get_random_music(exclude_current=True)
            if next_music_file:
                current_music = next_music_file
                current_index = music_list.index(current_music) if current_music in music_list else -1
                logger.info(f"随机播放下一首: {current_music}")
                return play_music(current_music)
            else:
                return {"success": False, "message": "无法获取随机音乐"}
        else:
            # 顺序播放模式
            if loop_mode == 2:  # 列表循环模式
                current_index = (current_index + 1) % len(music_list)
            elif current_index < len(music_list) - 1:
                current_index += 1
            else:
                return {"success": False, "message": "已经是最后一首了"}
            
            current_music = music_list[current_index]
            return play_music(current_music)
    else:
        return {"success": False, "message": "音乐列表为空"}

def prev_music():
    """
    播放上一首音乐
    
    Returns:
        dict: {
            "success": bool,  # 操作是否成功
            "message": str    # 操作结果消息
        }
    """
    global current_index, current_music
    if not music_list:
        load_music_list()
    
    if music_list:
        if loop_mode == 2:  # 列表循环模式
            current_index = (current_index - 1) % len(music_list)
        elif current_index > 0:
            current_index -= 1
        else:
            return {"success": False, "message": "已经是第一首了"}
        
        current_music = music_list[current_index]
        return play_music(current_music)
    else:
        return {"success": False, "message": "音乐列表为空"}

def forward_music(seconds=10):
    """
    快进当前播放的音乐
    
    Args:
        seconds (int, optional): 快进的秒数，默认为10秒
    
    Returns:
        dict: {
            "success": bool,  # 操作是否成功
            "message": str    # 操作结果消息
        }
    """
    try:
        current_pos = mixer.music.get_pos() / 1000  # 获取当前播放位置（秒）
        mixer.music.set_pos(current_pos + seconds)
        logger.info(f"快进 {seconds} 秒")
        return {"success": True, "message": f"快进 {seconds} 秒"}
    except Exception as e:
        logger.error(f"快进失败: {e}")
        return {"success": False, "message": f"快进失败: {str(e)}"}

def rewind_music(seconds=10):
    """
    快退当前播放的音乐
    
    Args:
        seconds (int, optional): 快退的秒数，默认为10秒
    
    Returns:
        dict: {
            "success": bool,  # 操作是否成功
            "message": str    # 操作结果消息
        }
    """
    try:
        current_pos = mixer.music.get_pos() / 1000  # 获取当前播放位置（秒）
        new_pos = max(0, current_pos - seconds)  # 确保不小于0
        mixer.music.set_pos(new_pos)
        logger.info(f"快退 {seconds} 秒")
        return {"success": True, "message": f"快退 {seconds} 秒"}
    except Exception as e:
        logger.error(f"快退失败: {e}")
        return {"success": False, "message": f"快退失败: {str(e)}"}

def set_volume(volume):
    """
    设置播放音量
    
    Args:
        volume (float): 音量值，范围0.0-1.0
    
    Returns:
        dict: {
            "success": bool,  # 操作是否成功
            "message": str    # 操作结果消息
        }
    """
    try:
        # 确保音量在0-1之间
        volume = max(0, min(1, float(volume)))
        mixer.music.set_volume(volume)
        logger.info(f"音量已设置为 {int(volume * 100)}%")
        return {"success": True, "message": f"音量已设置为 {int(volume * 100)}%"}
    except Exception as e:
        logger.error(f"设置音量失败: {e}")
        return {"success": False, "message": f"设置音量失败: {str(e)}"}

def set_loop_mode(mode):
    """
    设置音乐播放循环模式
    
    Args:
        mode (int): 循环模式
            0: 不循环
            1: 单曲循环
            2: 列表循环
    
    Returns:
        dict: {
            "success": bool,  # 操作是否成功
            "message": str    # 操作结果消息
        }
    """
    global loop_mode
    try:
        mode = int(mode)
        # 验证模式值
        if mode not in [0, 1, 2]:
            return {"success": False, "message": "循环模式无效，请使用0(不循环)、1(单曲循环)或2(列表循环)"}
            
        loop_mode = mode
        # 单曲循环时设置pygame的循环播放
        if mode == 1 and current_music and is_playing:
            mixer.music.play(-1)
        
        logger.info(f"循环模式已设置为: {mode}")
        modes = {0: "不循环", 1: "单曲循环", 2: "列表循环"}
        return {"success": True, "message": f"循环模式已设置为: {modes.get(mode, '未知')}"}
    except Exception as e:
        logger.error(f"设置循环模式失败: {e}")
        return {"success": False, "message": f"设置循环模式失败: {str(e)}"}

def set_play_mode(mode):
    """
    设置播放模式
    
    Args:
        mode (str): 播放模式 'random'=随机播放, 'sequential'=顺序播放
    
    Returns:
        dict: {
            "success": bool,  # 操作是否成功
            "message": str    # 操作结果消息
        }
    """
    global play_mode
    try:
        if mode not in ['random', 'sequential']:
            return {"success": False, "message": "播放模式无效，请使用'random'(随机播放)或'sequential'(顺序播放)"}
        
        play_mode = mode
        mode_names = {'random': '随机播放', 'sequential': '顺序播放'}
        logger.info(f"播放模式已设置为: {mode_names.get(mode, '未知')}")
        return {"success": True, "message": f"播放模式已设置为: {mode_names.get(mode, '未知')}"}
    except Exception as e:
        logger.error(f"设置播放模式失败: {e}")
        return {"success": False, "message": f"设置播放模式失败: {str(e)}"}

def get_status():
    """
    获取当前播放器状态信息
    
    Returns:
        dict: {
            "success": bool,  # 操作是否成功
            "data": dict      # 状态数据，包含当前播放音乐、播放状态、循环模式等
        }
    """
    global is_playing
    try:
        # 获取当前音乐的完整路径
        current_full_path = None
        if current_music:
            current_full_path = music_full_paths.get(current_music, os.path.join(MUSIC_FOLDER, current_music))
        
        status = {
            "current_music": current_music,  # 当前播放的音乐文件名
            "current_full_path": current_full_path,  # 当前播放的音乐完整路径
            "is_playing": is_playing,        # 是否正在播放
            "loop_mode": loop_mode,          # 循环模式
            "play_mode": play_mode,          # 播放模式
            "music_list": music_list,        # 音乐文件列表
            "music_full_paths": music_full_paths,  # 音乐文件完整路径映射
            "current_index": current_index   # 当前音乐在列表中的索引
        }
        return {"success": True, "data": status}
    except Exception as e:
        logger.error(f"获取状态失败: {e}")
        return {"success": False, "message": f"获取状态失败: {str(e)}"}

def search_music(keyword):
    """
    搜索音乐文件
    
    Args:
        keyword (str): 搜索关键词
    
    Returns:
        dict: {
            "success": bool,  # 操作是否成功
            "results": list,  # 搜索结果列表
            "full_paths": dict  # 搜索结果对应的完整路径
        }
    """
    if not music_list:
        load_music_list()
    
    # 使用关键词索引搜索
    results = search_music_by_keyword(keyword)
    
    # 构建结果的完整路径映射
    full_paths = {music: music_full_paths.get(music, os.path.join(MUSIC_FOLDER, music)) for music in results}
    
    logger.info(f"搜索关键词 '{keyword}'，找到 {len(results)} 个结果")
    return {"success": True, "results": results, "full_paths": full_paths}

# 音乐播放器MCP工具函数
@mcp.tool()
def music_player(action: str, **kwargs) -> dict:
    """
    音乐播放器MCP工具函数，提供所有音乐控制功能的统一入口
    
    这是向小智AI暴露的主要接口，通过指定不同的action参数来执行各种音乐播放操作。
    支持自然语言命令匹配，例如"播放音乐"、"播放周杰伦的七里香"等。
    
    Args:
        action (str): 要执行的操作命令
            - play: 播放音乐
            - pause: 暂停音乐
            - unpause: 恢复播放
            - stop: 停止音乐
            - next: 下一首
            - prev: 上一首
            - forward: 快进
            - rewind: 快退
            - volume: 设置音量
            - loop: 设置循环模式
            - status: 获取当前状态
            - list: 获取音乐列表
            - search: 搜索音乐
            - 其他自然语言命令: 会被解析为相应操作
        **kwargs: 操作相关的参数
            - play操作参数: file_name (str, 可选) - 要播放的文件名
            - forward/rewind操作参数: seconds (int, 可选, 默认10) - 快进/快退秒数
            - volume操作参数: value (float, 必需) - 音量值(0.0-1.0)
            - loop操作参数: mode (int, 必需) - 循环模式(0=不循环,1=单曲循环,2=列表循环)
            - search操作参数: keyword (str, 必需) - 搜索关键词
    
    Returns:
        dict: 包含操作结果的字典
            - success (bool): 操作是否成功
            - message (str): 操作结果消息
            - data (dict, 可选): 状态信息数据
            - music_list (list, 可选): 音乐列表数据
            - results (list, 可选): 搜索结果列表
    """
    # 确保音乐列表已加载（优化）
    if not music_list:
        load_music_list()
        logger.info(f"响应请求时加载音乐列表: {len(music_list)} 首")
    
    # 处理自然语言命令解析
    original_action = action  # 保存原始动作参数，用于日志记录
    target_song = None
    
    # 将action转为小写以便进行命令匹配
    action_lower = action.lower()
    
    # 解析自然语言命令
    if "播放" in action_lower or "放歌" in action_lower:
        # 这是一个播放命令
        action = "play"
        
        # 特殊处理: 播放第N首
        if "第" in action_lower and "首" in action_lower:
            try:
                # 提取数字部分
                import re
                match = re.search(r'第(\d+)首', action_lower)
                if match:
                    song_index = int(match.group(1)) - 1  # 转为0-based索引
                    logger.info(f"接收到播放第{song_index + 1}首的命令")
                    # 检查索引是否有效
                    if 0 <= song_index < len(music_list):
                        target_song = music_list[song_index]
                        logger.info(f"将播放第{song_index + 1}首: {target_song}")
                    else:
                        logger.warning(f"索引无效: {song_index + 1}, 音乐列表长度: {len(music_list)}")
                        return {"success": False, "message": f"音乐列表只有{len(music_list)}首歌曲，请选择有效范围"}
                else:
                    logger.warning("无法解析'播放第N首'命令格式")
            except Exception as e:
                logger.error(f"解析播放第N首命令时出错: {e}")
        else:
            # 尝试提取歌曲名称
            # 移除常见的命令前缀
            for prefix in ["播放", "放歌", "播放本地", "播放", "播放音乐", "放一首", "听"]:
                if action_lower.startswith(prefix.lower()):
                    # 提取歌曲名称（去掉前缀）
                    song_part = action[len(prefix):].strip()
                    if song_part:
                        # 进一步清理，移除可能的后缀
                        for suffix in ["吧", "好吗", "可以吗", "吗", "" ]:
                            if song_part.endswith(suffix):
                                target_song = song_part[:-len(suffix)].strip() if suffix else song_part.strip()
                                break
                        # 如果还有歌手信息，尝试更好地匹配
                        if "的" in target_song:
                            # 处理"周杰伦的七里香"这种格式
                            parts = target_song.split("的")
                            if len(parts) >= 2:
                                # 我们有歌手和歌曲名，尝试精确匹配
                                singer = parts[0].strip()
                                song = "的".join(parts[1:]).strip()
                                logger.info(f"尝试匹配: 歌手={singer}, 歌曲={song}")
                                target_song = song  # 使用歌曲名作为主要匹配条件
    elif "暂停" in action_lower or "停止" in action_lower:
        action = "pause"
    elif "继续" in action_lower or "恢复" in action_lower:
        action = "unpause"
    elif "停止" in action_lower:
        action = "stop"
    elif "下一首" in action_lower or "下首" in action_lower:
        action = "next"
    elif "上一首" in action_lower or "上首" in action_lower:
        action = "prev"
    elif "列表" in action_lower or "歌单" in action_lower or "曲目" in action_lower:
        action = "list"
    elif "音量" in action_lower or "声音" in action_lower:
        action = "volume"
    elif "循环" in action_lower:
        action = "loop"
    elif "随机" in action_lower or "随机播放" in action_lower:
        action = "random"
    elif "顺序" in action_lower or "顺序播放" in action_lower:
        action = "sequential"
    elif "状态" in action_lower or "现在" in action_lower or "正在" in action_lower:
        action = "status"
    
    logger.info(f"处理命令: '{original_action}' -> 转换为操作: '{action}', 目标歌曲: '{target_song}'")
    
    # 根据不同的action调用相应的功能函数
    if action == "play":
        # 优先使用提取到的歌曲名
        file_name = target_song
        
        # 处理keyword参数（直接在主参数中）
        if not file_name and "keyword" in kwargs:
            file_name = kwargs.get("keyword")
            logger.info(f"从keyword参数获取歌曲名: {file_name}")
        # 处理嵌套的kwargs格式
        elif not file_name and "kwargs" in kwargs and isinstance(kwargs.get("kwargs"), dict):
            nested_kwargs = kwargs.get("kwargs")
            if "file_name" in nested_kwargs:
                file_name = nested_kwargs.get("file_name")
                logger.info(f"从嵌套kwargs获取file_name: {file_name}")
            elif "keyword" in nested_kwargs:
                file_name = nested_kwargs.get("keyword")
                logger.info(f"从嵌套kwargs获取keyword: {file_name}")
        # 处理直接的file_name参数
        elif not file_name and "file_name" in kwargs:
            file_name = kwargs.get("file_name")
            logger.info(f"从file_name参数获取歌曲名: {file_name}")
        
        # 如果没有指定歌曲名，直接播放第一首或继续播放
        if not file_name:
            logger.info("未指定歌曲名，播放第一首音乐")
            
        result = play_music(file_name)
        
        # 改进错误信息处理
        if not result["success"]:
            # 如果是找不到歌曲的错误，提供更友好的提示
            if "未找到" in result["message"] or "找不到" in result["message"]:
                if file_name:
                    result["message"] = f"未找到歌曲'{file_name}'，请尝试更准确的歌曲名，或使用'播放列表'查看所有歌曲"
                elif "列表为空" in result["message"]:
                    result["message"] = "音乐列表为空，请检查d:/MCP/0/music/文件夹中是否有音频文件"
        return result
    elif action == "pause":
        return pause_music()
    elif action == "unpause":
        return unpause_music()
    elif action == "stop":
        return stop_music()
    elif action == "next":
        return next_music()
    elif action == "prev":
        return prev_music()
    elif action == "forward":
        seconds = kwargs.get("seconds", 10)
        return forward_music(seconds)
    elif action == "rewind":
        seconds = kwargs.get("seconds", 10)
        return rewind_music(seconds)
    elif action == "volume":
        volume = kwargs.get("value")
        if volume is None:
            return {"success": False, "message": "请提供音量值"}
        return set_volume(float(volume))
    elif action == "loop":
        mode = kwargs.get("mode")
        if mode is None:
            return {"success": False, "message": "请提供循环模式"}
        return set_loop_mode(int(mode))
    elif action == "status":
        return get_status()
    elif action == "list":
        if not music_list:
            load_music_list()
        # 返回音乐列表及其完整路径
        music_info = [{"file_name": music, "full_path": music_full_paths.get(music, os.path.join(MUSIC_FOLDER, music))} for music in music_list]
        return {"success": True, "music_list": music_list, "music_full_paths": music_full_paths, "music_info": music_info}
    elif action == "search":
        keyword = kwargs.get("keyword")
        if not keyword:
            return {"success": False, "message": "请提供搜索关键词"}
        return search_music(keyword)
    elif action == "random":
        return set_play_mode("random")
    elif action == "sequential":
        return set_play_mode("sequential")
    else:
        return {"success": False, "message": f"未知操作: {action}，请使用正确的操作命令"}

# 启动MCP服务器
if __name__ == "__main__":
    """
    程序入口点，启动MCP服务器
    
    初始化时加载音乐列表并启动MCP服务，监听来自小智AI的请求。
    使用stdio传输模式与MCP客户端通信。
    """
    try:
        # 初始化时加载音乐列表
        load_music_list()
        
        # 启动MCP服务器
        logger.info("音乐播放器MCP服务已启动，正在监听来自小智AI的请求")
        logger.info(f"已加载 {len(music_list)} 首音乐，存放在: {MUSIC_FOLDER}")
        logger.info(f"已建立 {len(music_index)} 个关键词索引，支持智能搜索")
        logger.info("您可以通过小智AI命令如'播放音乐'、'播放日不落'、'播放周杰伦的歌'等来控制音乐播放")
        logger.info("支持的命令：播放音乐、播放[歌曲名]、播放[歌手名]的歌、下一首、暂停、继续、停止、随机播放、顺序播放、音量调整等")
        
        mcp.run(transport="stdio")
    except Exception as e:
        logger.error(f"启动服务失败: {e}")
        print(f"错误: {e}")
        # 显示更友好的错误提示，帮助用户诊断问题
        print("\n故障排除提示:")
        print("1. 确保已安装pygame库: pip install pygame")
        print("2. 确认音乐文件夹路径正确: d:/MCP/0/music/")
        print("3. 检查是否有MP3文件在音乐文件夹中")
        print("4. 以管理员权限运行程序")
        sys.exit(1)